package com.cxx.purchasecharge.component.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cxx.purchasecharge.component.bean.ActionResult;
import com.cxx.purchasecharge.component.bean.CustomerBean;
import com.cxx.purchasecharge.component.bean.DataGridRequestForm;
import com.cxx.purchasecharge.component.bean.GenericPagingResult;
import com.cxx.purchasecharge.component.bean.LoginUser;
import com.cxx.purchasecharge.component.bean.PCApplicationContext;
import com.cxx.purchasecharge.component.bean.PaymentBean;
import com.cxx.purchasecharge.component.bean.SearchRequestForm;
import com.cxx.purchasecharge.component.exception.ApplicationException;
import com.cxx.purchasecharge.component.utils.AjaxUtils;
import com.cxx.purchasecharge.component.utils.BeanConvertUtils;
import com.cxx.purchasecharge.component.utils.ComponentConstants;
import com.cxx.purchasecharge.component.utils.MessageProperties;
import com.cxx.purchasecharge.core.model.CustomerTypeCode;
import com.cxx.purchasecharge.core.model.PaymentSearchForm;
import com.cxx.purchasecharge.core.model.persistence.Customer;
import com.cxx.purchasecharge.core.model.persistence.Payment;
import com.cxx.purchasecharge.dal.PaymentDao;
import com.cxx.purchasecharge.service.AuditLogService;
import com.cxx.purchasecharge.service.QueryService;

@Controller
@RequestMapping ("/customerPay")
public class CustomerPayManager
{
    private static final Logger logger = Logger.getLogger (CustomerPayManager.class);

    @Autowired
    private QueryService queryService;
    @Autowired
    private AuditLogService auditLogService;
    @Autowired
    private PaymentDao paymentDao;
    @Autowired
    private PCApplicationContext pcContext;

    @RequestMapping (value = "/")
    public String redirectToCustomerManagement (ModelMap model)
    {
        return "customerPayManagement";
    }

    @RequestMapping (value = "/getAll", method = RequestMethod.POST)
    public @ResponseBody
    String getCustomers (DataGridRequestForm dataGridRequestForm, HttpServletRequest request) throws Exception
    {
        logger.debug (dataGridRequestForm);
        int page = dataGridRequestForm.getPage () - 1;
        int size = dataGridRequestForm.getRows ();
        String sortField = parseSortField (dataGridRequestForm.getSort ());
        String order = dataGridRequestForm.getOrder ();
        Pageable pageable = new PageRequest (page, size, new Sort ("asc".equalsIgnoreCase (order) ? Direction.ASC
                                                                                                 : Direction.DESC,
                                                                   sortField));
        String searchKey = (null == dataGridRequestForm.getSearchKey () ? "" : dataGridRequestForm.getSearchKey ()
                                                                                                  .trim ());
        LoginUser loginUser = pcContext.getLoginUser (request);
        if (null != loginUser)
        {
            Page <Customer> customerPage = queryService.findByFuzzy (CustomerTypeCode.CUSTOMER, pageable, searchKey,
                                                                     loginUser.getUserId (), loginUser.isAdmin ());
            List <Customer> customerList = customerPage.getContent ();

            long total = customerPage.getTotalElements ();
            GenericPagingResult <CustomerBean> customerPagingResult = new GenericPagingResult <CustomerBean> ();
            List <CustomerBean> customerBeans = BeanConvertUtils.customerList2CustomerBeanList (customerList);
            customerPagingResult.setRows (customerBeans);
            customerPagingResult.setTotal (total);
            
            float sumUnpay = queryService.countCustomerUnpay (CustomerTypeCode.CUSTOMER, searchKey,
                                                              loginUser.getUserId (), loginUser.isAdmin ());
            List<Map<String, String>> footer = new ArrayList <Map<String,String>> ();
            Map<String, String> map = new HashMap <String, String>();
            map.put ("dealMoney", "合计: " + sumUnpay);
            footer.add (map);
            customerPagingResult.setFooter (footer);

            JSONObject jsonObject = JSONObject.fromObject (customerPagingResult);
            return jsonObject.toString ();
        }
        else
        {
            throw new ApplicationException ();
        }
    }

    private String parseSortField (final String sortField)
    {
        String sortFieldAfterParse = "shortName";
        if (!StringUtils.isBlank (sortField))
        {
            if (ComponentConstants.REG_FUND.equalsIgnoreCase (sortField))
            {
                sortFieldAfterParse = ComponentConstants.REGISTER_FUND;
            }
            else if (ComponentConstants.REG_DATE.equalsIgnoreCase (sortField))
            {
                sortFieldAfterParse = ComponentConstants.REGISTER_DATE;
            }
        }
        return sortFieldAfterParse;
    }

    @RequestMapping (value = "/getPaymentByCustomer", method = RequestMethod.POST)
    public @ResponseBody
    String getPaymentByCustomer (long customerId)
    {
        List <Payment> payments = paymentDao.findByCustomerId (customerId);
        JSONArray jsonArr = JSONArray.fromObject (BeanConvertUtils.paymentList2PaymentBeanList (payments));
        return jsonArr.toString ();
    }

    @RequestMapping (value = "/getPaymentByCustomer2", method = RequestMethod.POST)
    public @ResponseBody
    String getPaymentByCustomer2 (DataGridRequestForm dataGridRequestForm, SearchRequestForm orderSearchRequestForm)
    {
        logger.debug (dataGridRequestForm);
        int page = dataGridRequestForm.getPage () - 1;
        int size = dataGridRequestForm.getRows ();
        String sortField = parseSortField (dataGridRequestForm.getSort ());
        String order = dataGridRequestForm.getOrder ();
        Pageable pageable = new PageRequest (page, size, new Sort ("asc".equalsIgnoreCase (order) ? Direction.ASC
                                                                                                 : Direction.DESC,
                                                                   sortField));

        PaymentSearchForm searchForm = BeanConvertUtils.searchRequestForm2PaymentSearchForm (orderSearchRequestForm);
        searchForm.setTypeCode (CustomerTypeCode.CUSTOMER);

        Page <Payment> paymentPage = paymentDao.findPagePaymentBy (searchForm, pageable);
        long total = paymentPage.getTotalElements ();
        GenericPagingResult <PaymentBean> payPagingResult = new GenericPagingResult <PaymentBean> ();
        payPagingResult.setRows (BeanConvertUtils.paymentList2PaymentBeanList (paymentPage.getContent ()));
        payPagingResult.setTotal (total);

        float sumPaid = paymentDao.countPaidBy (searchForm);
        List <Map <String, String>> footer = new ArrayList <Map <String, String>> ();
        Map <String, String> map = new HashMap <String, String> ();
        map.put (ComponentConstants.PAY_DATE, "实收款合计");
        map.put (ComponentConstants.PAID, sumPaid + "");
        footer.add (map);
        payPagingResult.setFooter (footer);

        JSONObject jsonObject = JSONObject.fromObject (payPagingResult);
        return jsonObject.toString ();
    }

    @Transactional
    @RequestMapping (value = "/updatePaid", method = RequestMethod.POST)
    public @ResponseBody
    String updatePaid (PaymentBean paymentBean, BindingResult result, HttpServletRequest request)
    {
        if (result.hasErrors ())
        {
            logger.error (result.getAllErrors ());
            ActionResult ar = ActionResult.badRequest ()
                                          .withMessage (MessageProperties.getConfig (ComponentConstants.GENERIC_MSG_REQUEST_ARGS_ERROR))
                                          .build ();
            return AjaxUtils.getJsonObject (ar);
        }
        else
        {
            ActionResult ar = ActionResult.createActionResult ().build ();
            try
            {
                String user = pcContext.getLoginUser (request).getUserId ();
                paymentBean.setOperator (user);
                Payment payment = BeanConvertUtils.paymentBean2Payment (paymentBean);
                auditLogService.addPayment (payment, user);
                ar = ActionResult.ok ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_UPDATE_SUCCESS,
                                                                                     ComponentConstants.MSG_CUSTOMER_PAID))
                                 .build ();
            }
            catch (Exception e)
            {
                logger.error (e.getMessage (), e);
                ar = ActionResult.serverError ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_UPDATE_FAIL,
                                                                                     ComponentConstants.MSG_CUSTOMER_PAID))
                                 .build ();
            }
            return AjaxUtils.getJsonObject (ar);
        }
    }

}
